﻿using System;
using System.ComponentModel;
using System.Xml;
using Moonlite.Data.EditorInterop.Internal;

namespace Moonlite.Data.EditorInterop
{
    [DefaultProperty("Id")]
    [DisplayName("Type")]
    public class ObjectUnit : IDeserializedObject
    {
        private int id;
        private float[] position;
        private float rotation;
        private float[] scale;
        private string type;
        private int player;
        private DeserializedObjectCollection children = new DeserializedObjectCollection();

        public int Id
        {
            get { return id; }
        }

        public float[] Position
        {
            get { return position; }
        }

        public float Rotation
        {
            get { return rotation; }
        }

        public float[] Scale
        {
            get { return scale; }
        }

        public string Type
        {
            get { return type; }
        }

        public int Player
        {
            get { return player; }
        }

        public DeserializedObjectCollection Children
        {
            get { return children; }
        }

        public override int GetHashCode()
        {
            return id.GetHashCode() ^ position.GetHashCode() ^ rotation.GetHashCode() ^ scale.GetHashCode() ^ type.GetHashCode() ^ player.GetHashCode();
        }

        public override string ToString()
        {
            return "[ObjectUnit Id=" + id.ToString() + ", UnitType=" + type + ", Player=" + player.ToString() + "]";
        }

        internal static IDeserializedObject Parse(XmlNode node)
        {
            int id = 0;
            float[] position = null;
            float rotation = 0f;
            float[] scale = null;
            string type = "";
            int player = 1;
            foreach (XmlAttribute attribute in node.Attributes)
            {
                switch (attribute.Name.ToLower())
                {
                    case "id":
                        id = int.Parse(attribute.Value);
                        break;
                    case "position":
                        position = FloatArrayUtils.ConvertStringToFloatArray(attribute.Value);
                        break;
                    case "rotation":
                        rotation = float.Parse(attribute.Value);
                        break;
                    case "scale":
                        scale = FloatArrayUtils.ConvertStringToFloatArray(attribute.Value);
                        break;
                    case "type":
                    case "unittype":
                        type = attribute.Value;
                        break;
                    case "player":
                        player = int.Parse(attribute.Value);
                        break;
                }
            }

            IDeserializedObject @object = new ObjectUnit(id, position, rotation, scale, type, player);
            GenericObjectNodeParser.Parse(node, @object);
            return @object;
        }

        internal ObjectUnit(int id, float[] position, float rotation, float[] scale, string type, int player)
        {
            if (id < 0)
            {
                throw new ArgumentOutOfRangeException("id");
            }

            if (position == null || position.Length == 0)
            {
                throw new ArgumentNullException("position");
            }

            if (rotation == float.NaN)
            {
                throw new ArgumentNullException("rotation");
            }

            if (scale == null || scale.Length == 0)
            {
                throw new ArgumentNullException("scale");
            }

            if (player < 1)
            {
                throw new ArgumentOutOfRangeException("player");
            }

            this.id = id;
            this.position = position;
            this.rotation = rotation;
            this.scale = scale;
            this.type = type;
            this.player = player;
        }
    }
}
